package dao

import (
	"fmt"
	"log"
	"reflect"

	"github.com/cyfqyb/fiber_demo/models"

	"github.com/cyfqyb/fiber_demo/global"
)

type TableInitializer func()

//var tableInitializers []TableInitializer

//func RegisterTableInitializer(initializer TableInitializer) {
//	tableInitializers = append(tableInitializers, initializer)
//}

func InitDao() {
	//遍历model_map
	for _, model := range models.ModelMap {
		if err := global.Db.AutoMigrate(reflect.New(model).Interface()); err != nil {
			log.Fatalf("Failed to initialize database table: %v", err)
		}
		log.Printf("Successfully initialized database table: %s", model.Name())
	}
}
func GetOneById[T any](id int) (*T, error) {
	var result T
	if err := global.Db.First(&result, id).Error; err != nil {
		return nil, err
	}
	return &result, nil
}

func InsertOne[T any](data T) error {
	if err := global.Db.Create(data).Error; err != nil {
		return err
	}
	return nil
}

func UpdateOne[T any](data T) error {
	if err := global.Db.Updates(data).Error; err != nil {
		return err
	}
	return nil
}

func DeleteOne[T any](data T) error {
	if err := global.Db.Delete(data).Error; err != nil {
		return err
	}
	return nil
}

func GetOne(model interface{}) (interface{}, error) {
	if model == nil {
		return nil, fmt.Errorf("model instance is nil")
	}
	result := global.Db.First(model)
	if result.Error != nil {
		return nil, result.Error
	}
	return model, nil
}

// GetList 函数用于根据传入的模型对象作为条件从数据库中查询多条记录
func GetList(model interface{}) (interface{}, error) {
	if model == nil {
		return nil, fmt.Errorf("model instance is nil")
	}

	// 创建一个切片类型的反射值来存储查询结果
	modelType := reflect.TypeOf(model)
	if modelType.Kind() == reflect.Ptr {
		modelType = modelType.Elem()
	}
	sliceType := reflect.SliceOf(modelType)
	resultSlice := reflect.New(sliceType).Elem()

	result := global.Db.Where(model).Find(resultSlice.Addr().Interface())
	if result.Error != nil {
		return nil, result.Error
	}

	return resultSlice.Interface(), nil
}
func GetAll[T any](model T) (interface{}, error) {
	modelType := reflect.TypeOf(model).Elem()
	sliceType := reflect.SliceOf(modelType)
	slice := reflect.New(sliceType).Interface()
	if err := global.Db.Find(slice).Error; err != nil {
		return nil, err
	}
	return slice, nil
}
